﻿using MCUPackage;
using MCUPackage.Utils;
using Newtonsoft.Json;
using System;
using System.ComponentModel;
using System.IO;
using System.Reflection;

namespace SxPackages.STC32G.Models
{
	[Serializable]
	class FreeOsOptions
	{
		protected STC32GQFP64 mParent = null;

		[Category("FreeRTOS"),
		DisplayName("使能"),
		DefaultValue(false),
		JsonProperty(Order = 100),
		Description("是否使能实时操作系统")]
		public bool Enable { get; set; } = false;

		[Category("FreeRTOS"),
		DisplayName("抢占方式"),
		DefaultValue(OSPreemptions.抢占式),
		Description("系统任务抢占方式")]
		public OSPreemptions Preemption { get; set; } = OSPreemptions.抢占式;

		[Category("FreeRTOS"),
		DisplayName("时间片调度"),
		DefaultValue(true),
		Description("是否使能时间片调度")]
		public bool EnableTimeSlicing { get; set; } = true;

		[Category("FreeRTOS"),
		DisplayName("系统节拍频率"),
		DefaultValue(1000),
		Description("时钟节拍频率，这里设置为1000,周期就是1ms")]
		public int SysTick => 1000;

		private int mMaxPriorities = 32;
		[Category("FreeRTOS"),
		DisplayName("最大优先级"),
		DefaultValue(32),
		Description("可使用的最大优先级, 取值范围为1~32")]
		public int MaxPriorities
		{
			get => mMaxPriorities;
			set
			{
				if (value != mMaxPriorities)
				{
					if (value < 1 || value > 32)
					{
						return;
					}
					mMaxPriorities = value;
				}
			}
		}

		[Category("FreeRTOS"),
		DisplayName("空闲任务堆栈"),
		DefaultValue(256),
		Description("空闲任务使用的堆栈大小")]
		public int IdleTaskSize { get; set; } = 256;

		[Category("FreeRTOS"),
		DisplayName("任务默认堆栈"),
		DefaultValue(128),
		Description("任务默认使用的堆栈大小")]
		public int TaskSize { get; set; } = 128;

		[Category("FreeRTOS"),
		DisplayName("任务名长度"),
		DefaultValue(8),
		Description("任务名名字字符串长度上限")]
		public int TaskNameMax { get; set; } = 8;

		[Category("FreeRTOS"),
		DisplayName("动态内存"),
		DefaultValue(true),
		Description("是否使能动态内存申请功能")]
		public bool EnableMalloc { get; set; } = true;

		[Category("FreeRTOS"),
		DisplayName("系统堆大小"),
		DefaultValue(2048),
		Description("系统所有总的堆大小, 单位:字节")]
		public int TotalHeap { get; set; } = 2048;

		[Category("FreeRTOS"),
		DisplayName("使能队列"),
		DefaultValue(false),
		Description("是否启用队列功能")]
		public bool EnableQueue { get; set; } = false;

		[Category("FreeRTOS"),
		DisplayName("使能互斥信号量"),
		DefaultValue(true),
		Description("是否使用互斥信号量")]
		public bool EnableMutex { get; set; } = true;

		[Category("FreeRTOS"),
		DisplayName("使能计数信号量"),
		DefaultValue(false),
		Description("是否使用计数信号量")]
		public bool EnableSemaphores { get; set; } = false;

		[Category("FreeRTOS"),
		DisplayName("使能运行时间统计"),
		DefaultValue(false),
		Description("是否启用运行时间统计功能")]
		public bool EnableStats { get; set; } = false;

		/// <summary>
		/// 生成项目文件
		/// </summary>
		/// <param name="aPath"></param>
		/// <returns></returns>
		public bool Generate(string aPath)
		{
			if (!this.Enable)
			{
				return false;
			}

			string srcPath = Path.Combine(mParent.TemplatePath, PrjPathTypes.Middlewares_FreeRTOS.ToDescription());
			if (!Directory.Exists(srcPath))
			{
				return false;
			}
			string dstPath = Path.Combine(aPath, PrjPathTypes.Middlewares_FreeRTOS.ToDescription());
			FileHelper.CopyDirectory(srcPath, dstPath);

			var files = Directory.GetFiles(srcPath);
			if (files != null && files.Length > 0)
			{
				foreach (var item in files)
				{
					if (item.EndsWith(".c", StringComparison.CurrentCultureIgnoreCase))
					{
						PrjTemplate.Append(PrjPathTypes.Middlewares_FreeRTOS, Path.GetFileName(item));
					}
				}
			}

			// 配置文件
			string file = "FreeRTOSConfig.h";
			var pairs = TemplateHelper.CreatePairs();
			Type type = this.GetType();
			PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
			string head = "Enable";
			foreach (var property in properties)
			{
				if (property.Name.Equals(head))
				{
					continue;
				}
				if (property.Name.StartsWith(head))
				{
					pairs[property.Name] = (bool)property.GetValue(this) ? "1" : "0";
				}
				else if (property.PropertyType == typeof(int))
				{
					pairs[property.Name] = property.GetValue(this).ToString();
				}
			}

			pairs["Preemption"] = this.Preemption == OSPreemptions.抢占式 ? "1" : "0";
			return mParent.CreateByTemplate(PrjPathTypes.Inc, aPath, file, true, pairs);
		}

		public FreeOsOptions(STC32GQFP64 aParent)
		{
			this.mParent = aParent;
		}
	}
}
